package me.ezjs.framework.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;

public class DateUtil {
    public static final long OneDayInMillis = 86400000;// 24 x 60 x 60 x 1000;

    /**
     * 年月日时分秒(无下划线) yyyyMMddHHmmss
     */
    public static final String dtLong = "yyyyMMddHHmmssSSS";

    /**
     * 完整时间 yyyy-MM-dd HH:mm:ss
     */
    public static final String simple = "yyyy-MM-dd HH:mm:ss";

    /**
     * 年月日(无下划线) yyyyMMdd
     */
    public static final String dtShort = "yyyyMMdd";


    /**
     * 将时间往后加几天.
     *
     * @param date
     * @param day
     * @return
     */
    public static Date addDay(Date date, int day) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, day);// 把日期往后增加一天.整数往后推,负数往前移动
        date = calendar.getTime(); // 这个时间就是日期往后推一天的结果
        return date;
    }

    /**
     * 判断是否为明天
     *
     * @param time
     */
    public static boolean isTomorrow(long time) {
        if (time >= getTomorrowMinTimeMillis() && time <= getTomorrowMaxTimeMillis()) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isToday(long time) {
        if (time >= getTodayMinTimeMillis() && time <= getTodayMaxTimeMillis()) {
            return true;
        } else {
            return false;
        }
    }

    private static long getTodayMaxTimeMillis() {
        return getOffsetMaxTimeMillis(0);
    }

    private static long getTodayMinTimeMillis() {
        return getOffsetMinTimeMills(0);
    }

    private static long getTomorrowMaxTimeMillis() {
        return getOffsetMaxTimeMillis(1);
    }

    private static long getTomorrowMinTimeMillis() {
        return getOffsetMinTimeMills(1);
    }

    /**
     * 获得指定偏移量日期的当天最大毫秒数
     *
     * @param offset 0为今天,1为明天,-1为昨天.
     * @return
     */
    private static long getOffsetMaxTimeMillis(int offset) {
        Calendar calendar = Calendar.getInstance();
        long currTime = System.currentTimeMillis();
        calendar.setTime(new Date(currTime));

        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        calendar.set(year, month, day, 23, 59, 59);
        long max = calendar.getTimeInMillis() / 1000 * 1000 + offset * OneDayInMillis;
        return max;
    }

    private static long getOffsetMinTimeMills(Date date, int offset) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        calendar = new GregorianCalendar();
        calendar.set(year, month, day, 0, 0, 0);
        long minToday = calendar.getTimeInMillis() / 1000 * 1000 + offset * OneDayInMillis;
        return minToday;
    }

    /**
     * 获得指定偏移量日期的当天最小毫秒数
     *
     * @param offset 0为今天0点的毫秒值,1为明天,-1为昨天.
     * @return
     */
    private static long getOffsetMinTimeMills(int offset) {
        return getOffsetMinTimeMills(new Date(), offset);
    }

    public static Date getToday() {
        long min = getOffsetMinTimeMills(0);// 获得今天0点的毫秒值.
        return new Date(min);
    }

    public static Date getNextDay(int n) {
        long min = getOffsetMinTimeMills(n);// 获得今天0点的毫秒值.
        return new Date(min);
    }

    public static Date getNextDayFirstSecond(Date day, int n) {
        long min = getOffsetMinTimeMills(day, n);// 获得0点的毫秒值.
        return new Date(min);
    }

    /**
     * 判断当前时间是否几点以后,24小时制.
     *
     * @param hour
     * @return
     */
    public static boolean afterHour(int hour) {
        long currTime = System.currentTimeMillis();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date(currTime));
        int h = calendar.get(Calendar.HOUR_OF_DAY);
        if (h >= hour) {
            return true;
        }
        return false;
    }

    /**
     * 判断当前时间是否指定时间之前,24小时制.
     *
     * @param hour
     * @return
     */
    public static boolean beforeHour(int hour, int minute) {
        long currTime = System.currentTimeMillis();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date(currTime));
        int h = calendar.get(Calendar.HOUR_OF_DAY);
        int m = calendar.get(Calendar.MINUTE);
        if (h > hour) {
            return false;
        }
        if (m >= minute) {
            return false;
        }
        return true;
    }

    public static String getTodayWeekDay() {
        return getWeekDay(new Date());
    }

    public static String getTomorrowWeekDay() {
        return getWeekDay(new Date(System.currentTimeMillis() + OneDayInMillis));
    }

    public static String getWeekDay(Date date) {
        int wd = getIntWeekDay(date);
        switch (wd) {
            case 1:
                return "周日";
            case 2:
                return "周一";
            case 3:
                return "周二";
            case 4:
                return "周三";
            case 5:
                return "周四";
            case 6:
                return "周五";
            case 7:
                return "周六";
            default:
                break;
        }
        return "";// impossible
    }

    private static int getIntWeekDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_WEEK);
    }

    public static String toLocal(Date today) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(today);
    }

    public static long getDayTime(String day) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return (df.parse(day).getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 返回系统当前时间(精确到毫秒),作为一个唯一的订单编号
     *
     * @return 以yyyyMMddHHmmss为格式的当前系统时间
     */
    public static String getOrderNum() {
        Date date = new Date();
        DateFormat df = new SimpleDateFormat(dtLong);
        return df.format(date).substring(2);
    }

    public static String getRefundNo() {
        Date date = new Date();
        DateFormat df = new SimpleDateFormat(dtLong);
        return df.format(date) + DateUtil.getThree();
    }

    /**
     * 获得交易号
     *
     * @return
     */
    public static String getTradeNum() {
        return "T" + DateUtil.getOrderNum() + DateUtil.getThree();
    }

    /**
     * 获得单个订单的内部交易号
     *
     * @return
     */
    public static String getItemTradeNum() {
        return "S" + DateUtil.getOrderNum() + DateUtil.getThree();
    }

    /**
     * 获取系统当前日期(精确到毫秒)，格式：yyyy-MM-dd HH:mm:ss
     *
     * @return
     */
    public static String getDateFormatter() {
        Date date = new Date();
        DateFormat df = new SimpleDateFormat(simple);
        return df.format(date);
    }

    /**
     * 获取系统当期年月日(精确到天)，格式：yyyyMMdd
     *
     * @return
     */
    public static String getDate() {
        Date date = new Date();
        DateFormat df = new SimpleDateFormat(dtShort);
        return df.format(date);
    }

    /**
     * 产生随机的三位数
     *
     * @return
     */
    public static String getThree() {
        Random rad = new Random();
        int r = rad.nextInt(1000);
        if (r < 10) {
            return "00" + r;
        } else if (r < 100) {
            return "0" + r;
        }
        return r + "";
    }

    public static void main(String[] args) throws ParseException {
        System.out.println("当前时间? " + toLocal(new Date()));

        System.out.println("今天日子? " + getToday());

        System.out.println("18点以后么? " + afterHour(18));

        System.out.println("某时间之前么? " + beforeHour(23, 50));

        // 获得周几
        System.out.println(getTodayWeekDay());
        System.out.println(getTomorrowWeekDay());

        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        System.out.println(df.parse("2014-11-03").getTime());

        df = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        System.out.println(df.parse("2014-11-03 23-59-59").getTime());

        System.out.println(DateUtil.getTodayMinTimeMillis());
        System.out.println(DateUtil.getTodayMaxTimeMillis());
        System.out.println(DateUtil.isTomorrow(new Date().getTime() - OneDayInMillis));
        System.out.println(DateUtil.isTomorrow(new Date().getTime() + OneDayInMillis));
        System.out.println(DateUtil.isToday(new Date().getTime()));
    }

    /**
     * 获取回收日期.
     * @param startDay
     * @param rentDay
     * @return
     */
    public static Date getRecoveryDay(Date startDay, int rentDay) {
        return getNextDayFirstSecond(startDay, rentDay + 1);
    }

}
